package wave;

import ast.*;
import base.*;
import java.util.Hashtable;
import java.util.Vector;
import trackmsg.EchoMsg;
import trackmsg.TrackCtrlMsg;

/**
 *
 * @author FUJISAI
 */
public class ASTAssignExecution extends WaveExecution {
    public ASTAssignExecution(WaveHeadParser parser, WaveEnvironment waveEnv){
        super(parser, waveEnv);
    }

    public void execute(ASTAssign asgn, String tail) {
        SimpleNode left = (SimpleNode)asgn.jjtGetChild(0);
        SimpleNode right = (SimpleNode)asgn.jjtGetChild(1);

        Vector vector = getASTNodeValue(right);
        System.out.println("DEBUG: " + vector);
        Hashtable fTab = this.waveEnv.getFrontalTable();

        /* Handle left cases */
        if (left instanceof ASTFrontalVar) {
            Utilities.WPPrint("DEBUG: " + fTab + "| LEFT: " + left.getString() + "|" + right);
            if(vector.contains("NONE")){
                fTab.remove(left.getString());
            } else {
                fTab.put(left.getString(), vector.clone());
            }
        }
        else if (left instanceof ASTNodalVar) {
            //Utilities.WPPrint("DEBUG: " + this.waveEnv.getCONTENT());
            Hashtable nTab = this.kn.getKNNode(
                        this.waveEnv.getCONTENT()).getNodalTable(waveEnv.getColor());
            if(vector.contains("NONE"))
                nTab.remove(left.getString());
            else
                nTab.put(left.getString(), vector.clone());
        }
        /**
         * left is Subscript: Na : 1 ...
         */
        else if (left instanceof ASTSubscript) {
            SimpleNode l_left = (SimpleNode)left.jjtGetChild(0);
            SimpleNode l_right = (SimpleNode)left.jjtGetChild(1);

            Vector v_index = new Vector();
            v_index = nodeToVector(l_right);
            Vector sVec = (Vector)vector.clone();

            if (l_left instanceof ASTFrontalVar) {
                Vector dVec = (Vector)fTab.get(l_left.getString());
                if(dVec == null){
                    dVec = new Vector();
                    fTab.put(l_left.getString(), dVec);
                }
                addToVector(dVec, v_index, sVec);
            }
            else if (l_left instanceof ASTNodalVar) {
               Hashtable nTab = this.kn.getKNNode(
                        this.waveEnv.getCONTENT()).getNodalTable(waveEnv.getColor());

                Vector dVec = (Vector)nTab.get(l_left.getString());
                if(dVec == null){
                    dVec = new Vector();
                    nTab.put(l_left.getString(), dVec);
                }
                addToVector(dVec, v_index, sVec);
            }
        }

        /**
         * Left is ASTIndexof: Fa::abc = ...
         */
        else if (left instanceof ASTIndexOf) {
            SimpleNode l_left = (SimpleNode)left.jjtGetChild(0);
            SimpleNode l_right = (SimpleNode)left.jjtGetChild(1);

            Vector v_index = new Vector();
            Vector v_cont = new Vector();
            Vector dVec = new Vector();
            v_cont = nodeToVector(l_right);
            Vector sVec = (Vector)vector.clone();

            if (l_left instanceof ASTFrontalVar) {
                dVec = (Vector)fTab.get(l_left.getString());
            }
            else if (l_left instanceof ASTNodalVar) {
                Hashtable nTab = this.kn.getKNNode(
                        this.waveEnv.getCONTENT()).getNodalTable(waveEnv.getColor());

                dVec = (Vector)nTab.get(l_left.getString());
            }

            for (int i=0;i<v_cont.size();i++) {
                for (int j=0;j<dVec.size();j++) {
                    if (v_cont.get(i).toString().compareTo(dVec.get(j).toString()) == 0) {
                        v_index.add(j+1);
                    }
                }
            }

            addToVector(dVec, v_index, sVec);

//            for (int i=0;i<v_index.size();i++) {
//                System.out.println("ABC");
//                System.out.println(v_index.get(i).toString());
//            }
        }
        /**
         * If C = NONE -> remove Node from Knowledge network
         */
        else if (left instanceof ASTContent && right instanceof ASTNone) {

        }
        /**
         * If L = NONE -> remove Link
         */
        else if (left instanceof ASTTraveledLink ) {
            if (right instanceof ASTNone){

            } else {
                Vector v = getASTNodeValue(right);
                if(v.size() > 0) {
                    String value = v.get(0).toString();
                    String currentNode = waveEnv.getCONTENT();
                    String linkName = waveEnv.getLINK();
                    String preNode = waveEnv.getPREDECESSOR();
                    kn.renameLink(preNode, currentNode, linkName, value);
                    waveEnv.setLINK(value);
                }
            }
        }

        if (waveEnv.getTrackAddress() != null && tail.equals("")) {
            //Neu tail ma rong thi gui echo la TRUE di
            TrackNode fromTrack = wi.getTrackForest().getTrackNode(waveEnv.getTrackAddress());
            TrackNode.Echo echo = TrackNode.Echo.TRUE;
            //Tao message echo va gui vao TrackQueue
            //Utilities.WPPrint("ME");
            TrackCtrlMsg msg = new EchoMsg(fromTrack, echo, waveEnv);
            wi.getTrackQueue().incoming(msg);
        } else if(!tail.equals("")){
            Wave newWave = new Wave(tail, new WaveEnvironment(waveEnv));
            waveQueue.incomingFront(newWave);
        }
        waveEnv.dump();
        Utilities.WPPrint("Executed Assign Done!");

    }

    public Vector nodeToVector(SimpleNode node){
        Vector vector = new Vector();

        if (node instanceof ASTArrayConst) {
            for (int i=0;i<node.jjtGetNumChildren(); i++) {
                SimpleNode child_node = (SimpleNode)node.jjtGetChild(i);
                vector.addAll(getASTNodeValue(child_node));
            }
        }
        else
            vector = getASTNodeValue(node);
        return vector;
    }

    /**
     * 
     * @param dVec
     * @param index
     * @param sVec
     */
    public void addToVector(Vector dVec, Vector v_index, Vector sVec) {
        for (int i=0; i<v_index.size(); i++) {
            int old_index = Integer.parseInt(v_index.elementAt(i).toString());
            int index = old_index + i*(sVec.size()-1);
            if (index > 0 && index < (dVec.size() + 1)) {
                for (int j=sVec.size()-1; j>=0; j-- ) {
                        dVec.add(index - 1, sVec.elementAt(j));
                }
                dVec.remove(index + sVec.size() - 1);
            }
            else if (index == 0) {
                for (int j=sVec.size()-1; j>=0; j-- ) {
                    dVec.add(index, sVec.elementAt(j));
                }
            }
            else if (index == dVec.size() + 1) {
                for (int j=0; j<sVec.size(); j++ ) {
                    dVec.add(sVec.elementAt(j));
                }
            }
        }
        for (int i=0; i<v_index.size(); i++)
            dVec.removeElement("NONE");
    }

    public boolean isNum (String str) {
        try{
            Integer.parseInt(str);
        } catch(NumberFormatException nfe) {
            return false;
        }
        return true;
    }
}